#define AE_USEMEMORYMANAGER
#define AE_OPENGL

#include <AEEngine.h>

#include <Windows.h>
#include <stdio.h>

//#include <core\threads\AEThread.h>
//#include "fileSystem.h"

#include <system/thread/AEThreadPool.h>
#include "VertexBuffer.h"
#include "Custom2DRenderLoop.h"

void TestMatrix();
void TestFileStreams();
void TestAETList();
void TestBoundingBox();
int memtest();
void TestThreads();
void TestRefObjects();
void TestMiniAllocator();
void TestArray();
void TestString();
void MemoryTest();
void TestMath();
void FloatTest();
void TestThreadPool();
void TestVector4f();
void TestMesh();
void TestShaderConstantTable();

void TestOGL();
void Test2D();
//AEMemoryManager ll;

int main( int argc, char* argv[] )
{
	_controlfp( _PC_24, _MCW_PC );
	AEEngineConfig ecConfig;

	ecConfig.uiWindowWidth = 800;
	ecConfig.uiWindowHeight = 600;
	ecConfig.bRunInWindowMode = 1;
	
//	hkMallocAllocator baseMalloc;
 
  //   hkMemoryRouter* memoryRouter = hkMemoryInitUtil::initDefault(&baseMalloc, hkMemorySystem::FrameInfo(1024 * 1024) );

	AEStackAllocator test(1024*16,"16KAppMainStack");
	//AEDefaultMemoryConfig dmc( &test, NULL);

	AEMemoryConfig::AEMemoryConfigInfo mcInfo( 1024*1024*8, 1024*1024 );
	//AEMemoryManager *lpMemMgr = dmc.MainInit( mcInfo );
 	InitMemorySystem( &test, mcInfo );

	//ll.SetHeapAllocator( &test );*/

	//AEEngine engine;
	//engine.Initialize();

	AEngine::Init( &ecConfig );
	TestMatrix();
	//TestOGL();
	//AEMemoryConfig *lpMemMgr = AEngine::GetMemConfig()->GetInstancePtr();

	//TestMesh();
	AEFileManager::GetInstance()->AddFileSystem( "my_root", "data" );
	AEFileManager::GetInstance()->AddSearchPath("$my_root/texture");
	AEFileManager::GetInstance()->AddSearchPath("$my_root/shaders");

	Test2D();

	//TestVector4f();
	//TestFileStreams();
	//TestShaderConstantTable();
	//TestVertexBuffer();
	//AEngine::GetTextureManager()->Load2DTextureFromFile( "texture1.bmp" );
	AEngine::InitWorld();

	Custom2DRenderLoop *lpMyRenderLoop = new Custom2DRenderLoop();
	lpMyRenderLoop->InitRenderLoop();
	AEngine::Run();

	//Sleep( 15000 );

	return 1;
	/*AEPropertyContainer pc;

	AEProperty *lpProp = new AEProperty();
	AEProperty pProp;

	lpProp->SetName( "PropertyPtr" );
	pProp.SetName( "PropertyRef" );

	int nValue = 5;
	lpProp->SetValue( nValue );

	pc.AddProperty( lpProp );
	nValue=10;
	lpProp->Bind( "Test", &nValue );

	int nn = lpProp->GetValue<int>();
	pProp.SetValue( 10 );

	*/

	//AEVector3 vc;
	//FloatTest();
	//TestMath();
	//TestThreadPool();
	//memtest();
	//AEngine::Init();
	//TestMiniAllocator();
	//MemoryTest();
	//TestString();
	//TestAETList();
	//TestBoundingBox();
	//TestThreads();
	//TestRefObjects();
	//TestAEFileSystem( 0 );
	//TestArray();
	//vc.IsZero();
	//vc.Set( 5 );

	//vc *= 4.3f;
	/*
	AEProcessor::GetInstance().GetNumCPU();
	AEProcessor::GetInstance().GetNumCPUAvailableForProcess();
	AEProcessor::GetInstance().AffinitizeThreadToProcessor(0);
	*/
	return 0;
}

/*#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;*/

void TestMatrix()
{
	AEVector4f vc1(4.0,3.0,3.0,0.0);
	AEVector4f vc2(-0.412878394, 0.852727056, -0.319980770,0.0 );
	AESimdFloat32 ff = vc2.GetDot<3>( vc1 );

	AEMatrix4f matProj;
	matProj.SetPerspectiveProjectionMatrixFromFovX( 45.0, 4.0f / 3.0f, 0.1f, 100.0f );
	/*glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
	glm::mat4 ortho = glm::ortho(0,800,0,600);*/
	AEMatrix4f matOrtho;
	matOrtho.SetOrthographicProjectionMatrix( 0, 800, 0, 600, 0.1, 100.0 );

	AEFLOAT32 fMatRes[16];
	matProj.Get( fMatRes, AEML_RowMajor );

	AEMatrix4f matLookAt;
	matLookAt.SetLookAtMatrix( AEVector4f( 4.0f, 3.0f, 3.0f ), AEVector4f( 0.0f, 0.0f, 0.0f ), AEVector4f( 0.0f, 1.0f, 0.0f ) );

	matLookAt.Get( fMatRes, AEML_RowMajor );

  /*  glm::mat4 View       = glm::lookAt(
                                                            glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
                                                            glm::vec3(0,0,0), // and looks at the origin
                                                            glm::vec3(0,1,0) ); // Head is up (set to 0,-1,0 to look upside-down)
*/
	matLookAt.SetIdentity();

	AEMatrix4f mat1, mat2, mat3;

	AEVector4f col0, col1, col2, col3;
	AEVector4f col10, col11, col12, col13;

	col0.Set( 1.111, 2.112, 3.113, 4.114 );
	col1.Set( 5.115, 6.116, 7.117, 8.118 );
	col2.Set( 9.119, 10.120, 11.121, 12.122 );
	col3.Set( 13.123, 14.124, 15.125, 16.126 );

	col10.Set( 17.127, 18.128, 19.129, 20.130 );
	col11.Set( 21.131, 22.132, 23.133, 24.134 );
	col12.Set( 25.134, 26.135, 27.136, 28.137 );
	col13.Set( 29.138, 30.139, 31.140, 32.141 );

	mat1.SetCols( col0, col1, col2, col3 );
	mat2.SetCols( col10, col11, col12, col13 );

	mat3.SetMul( mat1, mat2 );
	//mat3.Transpose();

	mat3.SetIdentity();

	mat3.SetOrthographicProjectionMatrix( 0, 800, 600, 0, -1, 1 );
	/*glm::mat4 projection = glm::ortho(0.0f, 800.0f, 600.0f, 0.0f, -1.0f, 1.0f);
	*/
	mat3.SetIdentity();
}

void TestOGL()
{
	/* Create a variable to hold the VBO identifier */
	GLuint triangleVBO;
 
	/* This is a handle to the shader program */
	GLuint shaderProgram;

	/* These pointers will receive the contents of our shader source code files */
	GLchar *vertexSource, *fragmentSource;

	/* These are handles used to reference the shaders */
	GLuint vertexShader, fragmentShader;

	const unsigned int shaderAttribute = 0;

	/* Vertices of a triangle (counter-clockwise winding) */
	/*float data[] = { 
                -1.0f, -1.0f, 0.0f,
                 1.0f, -1.0f, 0.0f,
                 0.0f,  1.0f, 0.0f,
        };*/

	float data[] = { 
                 100.0f, 100.0f, 0.0f,
                 200.0f, 100.0f, 0.0f,
                 100.0f,  50.0f, 0.0f,
        };
	/*---------------------- Initialise VBO - (Note: do only once, at start of program) ---------------------*/
	/* Create a new VBO and use the variable "triangleVBO" to store the VBO id */
	glGenBuffers(1, &triangleVBO);

	/* Make the new VBO active */
	glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);

	/* Upload vertex data to the video device */
	glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

	/* Specify that our coordinate data is going into attribute index 0(shaderAttribute), and contains three floats per vertex */
	glVertexAttribPointer(shaderAttribute, 3, GL_FLOAT, GL_FALSE, 0, 0);

	/* Enable attribute index 0(shaderAttribute) as being used */
	glEnableVertexAttribArray(shaderAttribute);

	/* Make the new VBO active. */
	glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
	/*-------------------------------------------------------------------------------------------------------*/

	/*--------------------- Load Vertex and Fragment shaders from files and compile them --------------------*/
	/* Read our shaders into the appropriate buffers */
	FILE *fp = fopen( "C:\\MyProjects\\AEngine\\bin\\win32\\Debug\\data\\shaders\\test.vs", "rt" );
	fseek( fp, 0, SEEK_END );
	int nLen = ftell(fp);
	fseek( fp, 0, SEEK_SET );
	vertexSource = new GLchar[nLen+1];
	fread( vertexSource, nLen, 1, fp );
	fclose( fp );

	fp = fopen( "C:\\MyProjects\\AEngine\\bin\\win32\\Debug\\data\\shaders\\test.ps", "rt" );
	fseek( fp, 0, SEEK_END );
	nLen = ftell(fp);
	fseek( fp, 0, SEEK_SET );
	fragmentSource = new GLchar[nLen+1];
	fread( fragmentSource, nLen, 1, fp );
	fclose( fp );

	/* Assign our handles a "name" to new shader objects */
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

	/* Associate the source code buffers with each handle */
	glShaderSource(vertexShader, 1, (const GLchar**)&vertexSource, 0);
	glShaderSource(fragmentShader, 1, (const GLchar**)&fragmentSource, 0);

	/* Free the temporary allocated memory */
	free(vertexSource);
	free(fragmentSource);

	/* Compile our shader objects */
	glCompileShader(vertexShader);
	glCompileShader(fragmentShader);
	/*-------------------------------------------------------------------------------------------------------*/

	/*-------------------- Create shader program, attach shaders to it and then link it ---------------------*/
	/* Assign our program handle a "name" */
	shaderProgram = glCreateProgram();

	/* Attach our shaders to our program */
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);

	/* Bind attribute index 0 (shaderAttribute) to in_Position*/
	/* "in_Position" will represent "data" array's contents in the vertex shader */
	glBindAttribLocation(shaderProgram, shaderAttribute, "in_Position");

	/* Link shader program*/
	glLinkProgram(shaderProgram);
	/*-------------------------------------------------------------------------------------------------------*/

	/* Set shader program as being actively used */
	glUseProgram(shaderProgram);

	/* Set background colour to BLACK */
	glClearColor(0.0, 0.0, 0.0, 1.0);

	/* Clear background with BLACK colour */
	glClear(GL_COLOR_BUFFER_BIT);

	/* Actually draw the triangle, giving the number of vertices provided by invoke glDrawArrays
	   while telling that our data is a triangle and we want to draw 0-3 vertexes 
	*/
	glDrawArrays(GL_TRIANGLES, 0, (sizeof(data) / 3) / sizeof(GLfloat));
	/*---------------------------------------------------------------*/
}


template class AEStringMap< AEUINT32 >;
template class AECachedHashMap<AEStringMapOperations, AEContainerHeapAllocator>;

void Test2D()
{
	GLfloat vertices[] = { 
        // Pos      // Tex
        0.0f, 64.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 0.0625f,
		64.0f, 0.0f, 0.1f, 0.0625f,

        64.0f, 0.0f, 0.1f, 0.0625f,
		64.0f, 64.0f, 0.1f, 0.0f,
        0.0f, 64.0f, 0.0f, 0.0f,

        64.0f, 64.0f, 0.0f, 0.0f,
        64.0f, 0.0f, 0.0f, 0.0625f,
		128.0f, 0.0f, 0.1f, 0.0625f,

        128.0f, 0.0f, 0.1f, 0.0625f,
		128.0f, 64.0f, 0.1f, 0.0f,
        64.0f, 64.0f, 0.0f, 0.0f,

    };

	/*GLfloat vertices[] = { 
        // Pos      // Tex
        0.0f, 0.0f, 0.0f, 0.0625f,
        1.0f, 0.0f, 0.1f, 0.0625f,
        1.0f, 1.0f, 0.1f, 0.0f, 
    
        1.0f, 1.0f, 0.1f, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 0.0625f
    };*/

	/*
   0.0-1.0  1.0-1.0
		+----+
		|   /|
		|  / |
		| /  |
		|/   |
		+----+
   0.0-0.0  1.0-0.0

	*/
	/*
	GLfloat vertices[] = { 
        // Pos      // Tex
        0.0f, 0.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 0.0f, 
    
        1.0f, 1.0f, 0.0484375f, 0.041015625f,
        0.0f, 1.0f, 0.0484375f, 0.041015625f,
        0.0f, 0.0f, 0.0484375f, 0.041015625f
    };*/

	/*GLfloat vertices[] = { 
			// Pos      // Tex
			0.0f, 1.0f, 0.0f, 1.0f,
			1.0f, 0.0f, 1.0f, 0.0f,
			0.0f, 0.0f, 0.0f, 0.0f, 
    
			0.0f, 1.0f, 0.0f, 1.0f,
			1.0f, 1.0f, 1.0f, 1.0f,
			1.0f, 0.0f, 1.0f, 0.0f
		};*/
	/*GLfloat vertices[] = { 
        // Pos      // Tex
        10.0f, 10.0f, 0.0f, 1.0f,
        20.0f, 10.0f, 1.0f, 0.0f,
        20.0f, 20.0f, 0.0f, 0.0f, 
    
        10.0f, 10.0f, 0.0f, 1.0f,
        20.0f, 20.0f, 1.0f, 1.0f,
        10.0f, 20.0f, 1.0f, 0.0f
    };*/
	struct MeshVertex
	{
	  AEFLOAT32 fXpos;
	  AEFLOAT32 fYpos;
	  AEFLOAT32 fTex1;
	  AEFLOAT32 fTex2;
	};

	int nNumVertices = 152 * 6; // 22 tiles * 6 vertici ognuna
	int nNumFloats = nNumVertices * 4; // 22 tiles * 6 vertici ognuna * 4 float a vertice

	GLfloat *lpMap = new GLfloat[ nNumFloats ]; 

	int nRow = 0;
	float fCol = 0;

	for( int i=0; i<nNumFloats; i+=24 )
	{
		int nTile = rand()%7;

        lpMap[i] = 0.0f + (64.0f * fCol);
		lpMap[i+1] = 64.0f + (16.0f * nRow);
		lpMap[i+2] = 0.0f + (0.1 * nTile);
		lpMap[i+3] = 0.0f;

        lpMap[i+4] = 0.0f + (64.0f * fCol);
		lpMap[i+5] = 0.0f + (16.0f * nRow);
		lpMap[i+6] = 0.0f + (0.1 * nTile);
		lpMap[i+7] = 0.0625f;

		lpMap[i+8] = 64.0f + (64.0f * fCol);
		lpMap[i+9] = 0.0f + (16.0f * nRow);
		lpMap[i+10] = 0.1f + (0.1 * nTile);
		lpMap[i+11] = 0.0625f;


        lpMap[i+12] = 64.0f + (64.0f * fCol);
		lpMap[i+13] = 0.0f + (16.0f * nRow);
		lpMap[i+14] = 0.1f + (0.1 * nTile);
		lpMap[i+15] = 0.0625f;

		lpMap[i+16] = 64.0f + (64.0f * fCol);
		lpMap[i+17] = 64.0f + (16.0f * nRow);
		lpMap[i+18] = 0.1f + (0.1 * nTile);
		lpMap[i+19] = 0.0f;

        lpMap[i+20] = 0.0f + (64.0f * fCol);
		lpMap[i+21] = 64.0f + (16.0f * nRow);
		lpMap[i+22] = 0.0f + (0.1 * nTile);
		lpMap[i+23] = 0.0f;

		fCol+=1.0f;
		if( fCol > 9.9 )
		{
			nRow++;

			if( nRow % 2 != 0 )
				fCol = -0.5f;
			else
				fCol = 0.0f;
		}
	}

	// set up vertex format
	AEVertexDescriptor desc;
	desc.m_sStride = sizeof(MeshVertex);
	desc.m_sPosOfs = offsetof(MeshVertex, fXpos) | AEVERTEXDESC_FORMAT_FLOAT4;
	//desc.m_sTexCoordOfs[0] = offsetof(MeshVertex, fTex1) | AEVERTEXDESC_FORMAT_FLOAT2;

	AEMeshBufferPtr spMeshBuffer = new AEMeshBuffer( desc, nNumVertices, AEPRIMITIVETYPE_TRILIST, 0, nNumVertices/3, AEMEMUSAGE_STATIC );
	spMeshBuffer->FlagAsLoaded();

	MeshVertex* pVertex = static_cast<MeshVertex*>(spMeshBuffer->LockVertices(AELOCKFLAG_DISCARDABLE));
	//memcpy( pVertex, &vertices, sizeof(MeshVertex)*nNumVertices);
	memcpy( pVertex, lpMap, sizeof(MeshVertex)*nNumVertices);
	spMeshBuffer->UnLockVertices();

	AEStaticMeshPtr spStaticMesh = new AEStaticMesh();
	spStaticMesh->AllocateSubmeshes(1);
	spStaticMesh->SetMeshBuffer( spMeshBuffer );

	AEStaticSubmesh *lpSubMesh = spStaticMesh->GetSubmesh(0);
	lpSubMesh->SetRenderVertexRange( 0, nNumVertices );

	AEMatrix4f matModel;
	matModel.SetIdentity();
	//matModel.SetRotationMatrixZ( 20.0f );
	/*glm::mat4 model;
	model = glm::scale(model, glm::vec3(10.0f, 10.0f, 1.0f)); */

	//matModel.SetScalingMatrix( AEVector4f( 0.5f, 0.5f, 1.0f, 1.0f ) );

	//matModel.SetTranslationMatrix( AEVector4f( 10.0f, 0.0f, 0.0f, 1.0f ) );

	AEStaticMeshInstance *lpInst = spStaticMesh->CreateInstance( matModel );

	AEVisibilityZone *lpZone = new AEVisibilityZone();
	AESceneManagerI *lpMgr = AEngine::GetSceneManager();
	lpMgr->AddVisibilityZone( lpZone );
	AEStaticSubmeshInstance *lpSMInst = lpInst->GetSubmeshInstance(0);
	//AEStaticSubmeshInstance *lpSMInst2 = lpInst2->GetSubmeshInstance(0);
	lpZone->AddStaticGeometryInstance( lpSMInst );

	AEMaterial *lpMat = new AEMaterial();
	lpMat->SetTextureFile( AEMaterialTextures::AETEXTURETYPE_DIFFUSE, "tiles64x64.png" );
	lpSMInst->SetMaterial( lpMat );
}

void TestMesh()
{
	struct MeshVertex
	{
	  AEFLOAT32 fXpos;
	  AEFLOAT32 fYpos;
	  AEFLOAT32 fZpos;

	  AEFLOAT32 fColR;
	  AEFLOAT32 fColG;
	  AEFLOAT32 fColB;
	};

	// set up vertex format
	AEVertexDescriptor desc;
	desc.m_sStride = sizeof(MeshVertex);
	desc.m_sPosOfs = offsetof(MeshVertex, fXpos) | AEVERTEXDESC_FORMAT_FLOAT3;
	desc.m_sColorOfs = offsetof(MeshVertex, fColR) | AEVERTEXDESC_FORMAT_FLOAT3;
	//desc.m_sTexCoordOfs[0] = offsetof(MeshVertex, fUtex);

	//MeshVertex triangle[6];
	/*
	triangle[0].fXpos = -1.0f;
	triangle[0].fYpos = -1.0f;
	triangle[0].fZpos = 0.0f;
	triangle[0].fColR = 1.0f;
	triangle[0].fColG = 0.0f;
	triangle[0].fColB = 1.0f;

	triangle[1].fXpos = 1.0f;
	triangle[1].fYpos = -1.0f;
	triangle[1].fZpos = 0.0f;
	triangle[1].fColR = 1.0f;
	triangle[1].fColG = 0.0f;
	triangle[1].fColB = 0.0f;

	triangle[2].fXpos = 0.0f;
	triangle[2].fYpos = 1.0f;
	triangle[2].fZpos = 0.0f;
	triangle[2].fColR = 0.0f;
	triangle[2].fColG = 1.0f;
	triangle[2].fColB = 1.0f;


	triangle[0].fXpos = -1.0f;
	triangle[0].fYpos = -1.0f;
	triangle[0].fZpos = 0.0f;
	triangle[0].fColR = 1.0f;
	triangle[0].fColG = 0.0f;
	triangle[0].fColB = 1.0f;

	triangle[1].fXpos = 1.0f;
	triangle[1].fYpos = -1.0f;
	triangle[1].fZpos = 0.0f;
	triangle[1].fColR = 1.0f;
	triangle[1].fColG = 0.0f;
	triangle[1].fColB = 0.0f;

	triangle[2].fXpos = 1.0f;
	triangle[2].fYpos = 1.0f;
	triangle[2].fZpos = 0.0f;
	triangle[2].fColR = 0.0f;
	triangle[2].fColG = 1.0f;
	triangle[2].fColB = 1.0f;

	triangle[3].fXpos = -1.0f;
	triangle[3].fYpos = -1.0f;
	triangle[3].fZpos = 0.0f;
	triangle[3].fColR = 1.0f;
	triangle[3].fColG = 0.0f;
	triangle[3].fColB = 1.0f;

	triangle[4].fXpos = 1.0f;
	triangle[4].fYpos = 1.0f;
	triangle[4].fZpos = 0.0f;
	triangle[4].fColR = 0.0f;
	triangle[4].fColG = 1.0f;
	triangle[4].fColB = 1.0f;

	triangle[5].fXpos = -1.0f;
	triangle[5].fYpos = 1.0f;
	triangle[5].fZpos = 0.0f;
	triangle[5].fColR = 0.0f;
	triangle[5].fColG = 1.0f;
	triangle[5].fColB = 1.0f;
	*/
	/*float triangle[] = {
		-0.5f,  0.5f, 1.0f, 0.0f, 0.0f, 0.0f, // Top-left
		 0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 1.0f, // Top-right
		 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f,// Bottom-right

		 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,// Bottom-right
		-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f,// Bottom-left
		-0.5f,  0.5f, 1.0f, 0.0f, 0.0f, 1.0f  // Top-left
	};*/

	/*float triangle[] = {
		-0.5f,  0.5f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
		 0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 1.0f,// Top-right
		 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f,// Bottom-right
		-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f  // Bottom-left
	};*/

	/*float triangle[] = {
		10.0f,  10.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
		 30.0f,  10.0f, 0.0f, 1.0f, 0.0f, 1.0f,// Top-right
		 30.0f, 30.0f, 0.0f, 0.0f, 1.0f, 1.0f,// Bottom-right
		10.0f, 30.0f, 0.0f, 1.0f, 1.0f, 0.0f  // Bottom-left
	};*/

	float triangle[] = {
		// front
		-1.0, -1.0,  1.0, 1.0, 0.0, 0.0,
		 1.0, -1.0,  1.0, 0.0, 1.0, 0.0,
		 1.0,  1.0,  1.0, 0.0, 0.0, 1.0,
		-1.0,  1.0,  1.0, 1.0, 1.0, 1.0,
		// back
		-1.0, -1.0, -1.0, 1.0, 0.0, 0.0,
		 1.0, -1.0, -1.0, 0.0, 1.0, 0.0,
		 1.0,  1.0, -1.0, 0.0, 0.0, 1.0,
		-1.0,  1.0, -1.0, 1.0, 1.0, 1.0
	  };

	/*
	triangle[0].fXpos = 100.0f;
	triangle[0].fYpos = 100.0f;

	triangle[1].fXpos = 200.0f;
	triangle[1].fYpos = 100.0f;

	triangle[2].fXpos = 150.0f;
	triangle[2].fYpos = 50.0f;
	*/
	//AEMeshBufferPtr spMeshBuffer = new AEMeshBuffer( desc, 6, AEPRIMITIVETYPE_TRILIST, 0, 2, AEMEMUSAGE_STATIC );
	AEMeshBufferPtr spMeshBuffer = new AEMeshBuffer( desc, 8, AEPRIMITIVETYPE_INDEXED_TRISTRIP, 36, 12, AEMEMUSAGE_STATIC );
	spMeshBuffer->FlagAsLoaded();

	MeshVertex* pVertex = static_cast<MeshVertex*>(spMeshBuffer->LockVertices(AELOCKFLAG_DISCARDABLE));
	memcpy( pVertex, &triangle, sizeof(MeshVertex)*8);
	spMeshBuffer->UnLockVertices();

	/*AEUINT16 elements[] = {
		0, 1, 2,
		2, 3, 0
	};*/

	 AEUINT16 elements[] = {
		// front
		0, 1, 2,
		2, 3, 0,
		// top
		3, 2, 6,
		6, 7, 3,
		// back
		7, 6, 5,
		5, 4, 7,
		// bottom
		4, 5, 1,
		1, 0, 4,
		// left
		4, 0, 3,
		3, 7, 4,
		// right
		1, 5, 6,
		6, 2, 1,
	  };

	AEUINT16 *lpIndex = static_cast<AEUINT16*>(spMeshBuffer->LockIndices( AELOCKFLAG_DISCARDABLE, 0, 36 ));
	memcpy( lpIndex, &elements, sizeof(AEUINT16)*36);
	spMeshBuffer->UnLockIndices();

	AEStaticMeshPtr spStaticMesh = new AEStaticMesh();
	spStaticMesh->AllocateSubmeshes(1);
	spStaticMesh->SetMeshBuffer( spMeshBuffer );

	AEStaticSubmesh *lpSubMesh = spStaticMesh->GetSubmesh(0);
	lpSubMesh->SetRenderVertexRange( 0, 8 );
	lpSubMesh->SetRenderRange( 0, 36 );
	//AEngine::GetMainRenderContext()->SetMeshBuffers(spMeshBuffer);
	AEMatrix4f matModel;
	matModel.SetIdentity();

	AEStaticMeshInstance *lpInst = spStaticMesh->CreateInstance( matModel );

	//AEMatrix4f matModel2;
	//matModel2.SetTranslationMatrix( AEVector4f( 2.0f, 0.0f, 0.0f, 1.0f ) );
	//AEStaticMeshInstance *lpInst2 = spStaticMesh->CreateInstance( matModel2 );

	AEVisibilityZone *lpZone = new AEVisibilityZone();
	AESceneManagerI *lpMgr = AEngine::GetSceneManager();
	lpMgr->AddVisibilityZone( lpZone );
	AEStaticSubmeshInstance *lpSMInst = lpInst->GetSubmeshInstance(0);
	//AEStaticSubmeshInstance *lpSMInst2 = lpInst2->GetSubmeshInstance(0);
	lpZone->AddStaticGeometryInstance( lpSMInst );
	//lpZone->AddStaticGeometryInstance( lpSMInst2 );

	AEMeshBufferCollection mb(10);
	mb.AppendEntry( spMeshBuffer );

}

void TestVector4f()
{
	AEVector4f vcTestVector1;
	AEVector4f vcTestVector2( 1.0f, 2.0f, 3.0f, 4.0f );
	// Da capire il costruttore con AEQuadFloat32

	AEVector4f vcTestVector3 = AEVector4f::ZeroVector();

	// Le costanti non sono allineate
	AEVector4f vcTestVector4 = AEVector4f::GetConstant<AEVectorConstant::AE_QUADREAL_0100>();

	AEVector4f vcTestVector5 = AEVector4f::GetConstant(AEVectorConstant::AE_QUADREAL_0001);

	vcTestVector1.SetZero();
	vcTestVector3.Set( 1.0f, 1.0f, 0.0f, 0.0f );
	vcTestVector3.SetAll( 10.0f );

	vcTestVector2.ZeroComponent<0>();
	vcTestVector2.ZeroComponent<1>();
	vcTestVector2.ZeroComponent<2>();
	vcTestVector2.ZeroComponent<3>();

	vcTestVector5.Set( 2.0f, -2.0f, 1.0f, -1.0f );
	vcTestVector3.Add( vcTestVector5 );

	vcTestVector3.Sub( vcTestVector5 );

	vcTestVector5.Set( 2.0f, 2.0f, 2.0f, 2.0f );
	vcTestVector3.Mul( vcTestVector5 );

	vcTestVector3.Mul( 2.0f );

	vcTestVector3.Div( vcTestVector5 );
	vcTestVector4.SetAdd( vcTestVector3, vcTestVector5 );

	vcTestVector3.Set( 2.0f, 2.0f, 2.0f, 2.0f );
	vcTestVector5.Set( 2.0f, 2.0f, 2.0f, 2.0f );
	vcTestVector4.SetSub( vcTestVector3, vcTestVector5 );

	vcTestVector4.SetMul( vcTestVector3, vcTestVector5 );
	vcTestVector4.SetMul( 3.0f, vcTestVector5 );

	vcTestVector3.Set( 7.0f, 7.0f, 7.0f, 7.0f );
	vcTestVector4.SetSubMul( vcTestVector3, vcTestVector5, 3.0f );

	vcTestVector3.Set( 7.0f, 7.0f, 7.0f, 7.0f );
	vcTestVector4.SetSubMul( vcTestVector3, vcTestVector5, vcTestVector5 );

	vcTestVector3.Set( 4.0f, 4.0f, 4.0f, 4.0f );
	vcTestVector4.SetAddMul( vcTestVector3, vcTestVector5, 3.0f );
	vcTestVector4.SetAddMul( vcTestVector3, vcTestVector5, vcTestVector5 );

	vcTestVector4.Set( 5.0f, 5.0f, 5.0f, 5.0f );
	vcTestVector4.AddMul( vcTestVector5, 3.0f );
	vcTestVector4.AddMul( 4.0f, vcTestVector5 );
	vcTestVector4.AddMul( vcTestVector5, vcTestVector3 );

	vcTestVector4.SubMul( vcTestVector5, 3.0f );
	vcTestVector4.SubMul( 4.0f, vcTestVector5 );
	vcTestVector4.SubMul( vcTestVector5, vcTestVector3 );

	vcTestVector3.Set( 2.0f, 3.0f, 4.0f, 0.0f );
	vcTestVector5.Set( 5.0f, 6.0f, 7.0f, 0.0f );
	vcTestVector4.SetCross( vcTestVector3, vcTestVector5 );

	AEQuadFloat32 a = _mm_shuffle_ps( vcTestVector3.m_qfVector, vcTestVector3.m_qfVector, _MM_SHUFFLE( 3, 0, 2, 1 ) );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 4.0f );
	vcTestVector4.SetHorizontalAdd<2>( vcTestVector3 );
	vcTestVector4.SetHorizontalAdd<3>( vcTestVector3 );
	vcTestVector4.SetHorizontalAdd<4>( vcTestVector3 );

	AESimdFloat32 simdFloat1 = vcTestVector4.GetHorizontalAdd<2>();
	simdFloat1 = vcTestVector4.GetHorizontalAdd<3>();
	simdFloat1 = vcTestVector4.GetHorizontalAdd<4>();

	simdFloat1 = vcTestVector4.GetHorizontalMul<2>();
	simdFloat1 = vcTestVector4.GetHorizontalMul<3>();
	simdFloat1 = vcTestVector4.GetHorizontalMul<4>();

	vcTestVector4.SetHorizontalMax<1>( vcTestVector3 );
	vcTestVector4.SetHorizontalMax<2>( vcTestVector3 );
	vcTestVector4.SetHorizontalMax<3>( vcTestVector3 );
	vcTestVector4.SetHorizontalMax<4>( vcTestVector3 );

	simdFloat1 = vcTestVector3.GetHorizontalMax<1>();
	simdFloat1 = vcTestVector3.GetHorizontalMax<2>();
	simdFloat1 = vcTestVector3.GetHorizontalMax<3>();
	simdFloat1 = vcTestVector3.GetHorizontalMax<4>();

	vcTestVector4.SetHorizontalMin<1>( vcTestVector3 );
	vcTestVector4.SetHorizontalMin<2>( vcTestVector3 );
	vcTestVector4.SetHorizontalMin<3>( vcTestVector3 );
	vcTestVector4.SetHorizontalMin<4>( vcTestVector3 );

	simdFloat1 = vcTestVector3.GetHorizontalMin<1>();
	simdFloat1 = vcTestVector3.GetHorizontalMin<2>();
	simdFloat1 = vcTestVector3.GetHorizontalMin<3>();
	simdFloat1 = vcTestVector3.GetHorizontalMin<4>();

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal( vcTestVector3 );
	
	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_SET_ZERO>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_SET_ZERO>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_SET_ZERO>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_SET_HIGH>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_SET_HIGH>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_SET_HIGH>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_SET_MAX>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_SET_MAX>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_SET_MAX>( vcTestVector3 );

	// c:\myprojects\aengine\aecorelib\include\core\math\vector\sse\aevector4f_sse.inl(636): error C2039: 'QuadFabs' : is not a member of 'AEMath'
	//vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	//vcTestVector3.SetReciprocal<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_SET_ZERO_AND_ONE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrt( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrt<AEMathAccuracyMode::AE_ACC_FULL, AEMathNegSqrtMode::AE_SQRT_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrt<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathNegSqrtMode::AE_SQRT_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrt<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathNegSqrtMode::AE_SQRT_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrt<AEMathAccuracyMode::AE_ACC_FULL, AEMathNegSqrtMode::AE_SQRT_SET_ZERO>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrt<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathNegSqrtMode::AE_SQRT_SET_ZERO>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrt<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathNegSqrtMode::AE_SQRT_SET_ZERO>( vcTestVector3 );


	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrtInverse( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrtInverse<AEMathAccuracyMode::AE_ACC_FULL, AEMathNegSqrtMode::AE_SQRT_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrtInverse<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathNegSqrtMode::AE_SQRT_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrtInverse<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathNegSqrtMode::AE_SQRT_IGNORE>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrtInverse<AEMathAccuracyMode::AE_ACC_FULL, AEMathNegSqrtMode::AE_SQRT_SET_ZERO>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrtInverse<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathNegSqrtMode::AE_SQRT_SET_ZERO>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 0.0f );
	vcTestVector3.SetSqrtInverse<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathNegSqrtMode::AE_SQRT_SET_ZERO>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 4.0f );
	vcTestVector3.SetNeg<1>( vcTestVector3 );
	vcTestVector3.SetNeg<2>( vcTestVector3 );
	vcTestVector3.SetNeg<3>( vcTestVector3 );
	vcTestVector3.SetNeg<4>( vcTestVector3 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 1.0f );
	vcTestVector1.Set( 4.0f, -5.0f, 6.0f, 1.0f );
	simdFloat1 = vcTestVector3.GetDot<2>( vcTestVector1 );
	simdFloat1 = vcTestVector3.GetDot<3>( vcTestVector1 );
	simdFloat1 = vcTestVector3.GetDot<4>( vcTestVector1 );

	vcTestVector3.Set( 1.0f, 2.0f, 3.0f, 1.0f );
	simdFloat1 = vcTestVector3.Dot4xyz1( vcTestVector1 );

	vcTestVector1.Set( 1.0f, 2.0f, 3.0f, 1.0f );
	vcTestVector2.Set( 4.0f, -5.0f, 6.0f, 1.0f );

	vcTestVector3.SetDot<2>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDot<3>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDot<4>( vcTestVector1, vcTestVector2 );

	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_IGNORE>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_IGNORE>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_IGNORE>( vcTestVector1, vcTestVector2 );

	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_SET_HIGH>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_SET_HIGH>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_SET_HIGH>( vcTestVector1, vcTestVector2 );

	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_SET_MAX>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_SET_MAX>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_SET_MAX>( vcTestVector1, vcTestVector2 );

	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_SET_ZERO>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_SET_ZERO>( vcTestVector1, vcTestVector2 );
	vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_SET_ZERO>( vcTestVector1, vcTestVector2 );

	// c:\myprojects\aengine\aecorelib\include\core\math\vector\sse\aevector4f_sse.inl(636): error C2039: 'QuadFabs' : is not a member of 'AEMath'
	//vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_FULL, AEMathDivByZeroMode::AE_DIV_SET_ZERO_AND_ONE>( vcTestVector1, vcTestVector2 );
	//vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_23_BIT, AEMathDivByZeroMode::AE_DIV_SET_ZERO_AND_ONE>( vcTestVector1, vcTestVector2 );
	//vcTestVector3.SetDiv<AEMathAccuracyMode::AE_ACC_12_BIT, AEMathDivByZeroMode::AE_DIV_SET_ZERO_AND_ONE>( vcTestVector1, vcTestVector2 );

	vcTestVector3.SetDiv( vcTestVector1, vcTestVector2 );

	AEMatrix3f mat;
	vcTestVector1.Set( 6.0f, 4.0f, 2.0f, 0.0f );
	vcTestVector2.Set( 1.0f, -2.0f, 8.0f, 0.0f );
	vcTestVector3.Set( 1.0f, 5.0f, 7.0f, 0.0f );

	mat.SetColumn<0>( vcTestVector1 );
	mat.SetColumn<1>( vcTestVector2 );
	mat.SetColumn<2>( vcTestVector3 );

	AESimdFloat32 res = mat.GetDeterminant();
	return;
}


void TestShaderConstantTable()
{
	AEShaderConstantTable sctTable;
	AEShaderConstantTableEntry entry;
	
	entry.eValueType = AEValueType::AEVALUETYPE_FLOAT3;
	strcpy( entry.szVarname, "vecPos" );
	entry.nArrayElements = 1;
	entry.nRegisterIndex = 0;

	AEINT32 val = entry.GetRegisterCount();
	AEINT32 val1, val2;

	entry.GetRegisterRange( val1, val2 );
	val = entry.IsConstantBufferEntry();
	val = entry.IsSamplerType();
	val = entry.IsValid();
	
	AEShaderConstantTableEntry *lpRes;

	sctTable.AllocateEntries( 10 );
	sctTable.AddEntry( 0, &entry );

	entry.eValueType = AEValueType::AEVALUETYPE_FLOAT3;
	strcpy( entry.szVarname, "vecPos2" );
	entry.nArrayElements = 1;
	entry.nRegisterIndex = 12;

	sctTable.AddEntry( 12, &entry );

	lpRes = sctTable.FindByName("vecPos");
	lpRes = sctTable.FindByStartRegister( 1 );


}

void TestFileStreams()
{
	AEFileManager::GetInstance()->AddFileSystem( "my_root", "data" );
	AEFileManager::GetInstance()->AddSearchPath("$my_root/texture");
	AEFileManager::GetInstance()->AddSearchPath("$my_root/shaders");
	//AEFileManager::GetInstance()->AddSearchPath("$my_root");

	AEngine::GetTextureManager()->Load2DTextureFromFile( "testbmp24.bmp", 0 );
	// Path assoluto file non esistente -> KO
	//AEFileInStreamI *lpStream = AEFileManager::GetInstance()->Open( "$my_root/data/script4.txt" );
	// Path assoluto file esistente -> OK
	//AEFileInStreamI *lpStream = AEFileManager::GetInstance()->Open( "$my_root/data/script3.txt" );

	// Path relativo file non esistente -> KO
	//AEFileInStreamI *lpStream = AEFileManager::GetInstance()->Open( "data/sounds/sound14.mp3" );
	// Path relativo file esistente -> OK
	//AEFileInStreamI *lpStream = AEFileManager::GetInstance()->Open( "data/sounds/sound14.mp3" );

	// Path relativo ai searchPath file non esistente -> KO
	//AEFileInStreamI *lpStream = AEFileManager::GetInstance()->Open( "anim34.ani" );
	
	// Path relativo ai searchPath file esistente -> OK
	AEFileInStreamI *lpStream = AEFileManager::GetInstance()->Open( "anim1.ani" );

	//AEDiskFileSystem disk( "C:\\" );

	//AEFileInStreamI *lpStream = disk.Open( "c:\\test.txt", AEFileOpenFlags::FOF_READ | AEFileOpenFlags::FOF_WRITE );
	if( lpStream )
	{
		AEINT64 size = lpStream->GetSize();
		AEUINT8 *lpBuffer = new AEUINT8[size];
		lpStream->Read( lpBuffer, size );
		lpStream->Close();
	}
}

/*
void TestThreadPool()
{
	AEStackAllocator test(100000);
	AEMemoryManager ll;
	ll.SetHeapAllocator( &test );

	AEThreadPool tp;

	tp.Initialize(4);
	tp.Shutdown();
}
*/
void FloatTest()
{
	union float_bits
	{
		AEFLOAT32 f;
		AEUINT32 u;
	};

	float_bits fb;

	fb.f = 1.875f;

	AEINT32 res = AEMath::Float2Int( fb.f );


	float fHuge = 1.0e-40f; // valid single precision
	fHuge *= 1.0e38f; // result = infinity
	fHuge /= 1.0e38f; // ????

	printf("%d\n", res);
	res++;

}

void TestMath()
{
	AEFLOAT32 fRes=90.0f;
	AEFLOAT32 fRes1=90.0f;


	// Test AEVector4f
	AEVector4f vc, vc1;

	vc.SetZero();
	vc.Set( 1.0f, 2.0f, 3.0f, 4.0f );
	vc.SetAll( 1.0f );
	vc.ZeroComponent<0>();
	vc.ZeroComponent<1>();
	vc.ZeroComponent<2>();
	vc.ZeroComponent<3>();

	vc.Add( vc1 );
	vc.Sub( vc1 );
	vc.Mul( vc1 );
	vc.Mul( 2 );
	vc.Div( vc1 );
	vc.AddMul( vc1, vc1 );
	vc.AddXYZ( vc1 );

	DWORD dwStart = timeGetTime();
	for(int i=0; i<10000000; i++)
	{
		fRes = AEMath::Sin(fRes);
	}

	DWORD dwEnd = timeGetTime() - dwStart;
	printf("aemathlib sin %d - %f\n", dwEnd, fRes);

	dwStart = timeGetTime();
	for(int i=0; i<10000000; i++)
	{
		fRes1 = sinf(fRes1);
	}

	dwEnd = timeGetTime() - dwStart;
	printf("stdmathlib sin %d - %f\n", dwEnd, fRes1);
}

void TestString()
{
/*	AEStackAllocator test(10000);
	AEMemoryManager ll;
	ll.SetHeapAllocator( &test );

	AETString<char> str( "  gbel@gmailpit.cpp" );


	str.GetLength();
	str.IsEmpty();

	DWORD dwStart = timeGetTime();
	for(int i=0; i<1000000; i++)
	{
		str.ToUpper();
		//str.ToLower();
	}
	DWORD dwEnd = timeGetTime() - dwStart;

	str.ToLower();
	dwEnd = str.IndexOf( "luca" );
	dwEnd = str.LastIndexOf( '.' );
	dwEnd = str.LastIndexOf( ".cpp" );
	dwEnd = str.IndexOf( "an" );

	int nStart=5, nTot=-1;
	AETString<char> strCopiedAndDestroied = str.SubString( 0 );
	strCopiedAndDestroied.LTrim();
	strCopiedAndDestroied = "Gianluca";
	strCopiedAndDestroied += " stocazzo";

	char *lpRet = strCopiedAndDestroied.ToChar();
	strCopiedAndDestroied.RTrim();

	dwEnd = strCopiedAndDestroied.LastIndexOf( ".cpp" );

	strCopiedAndDestroied = str;
	dwEnd = strCopiedAndDestroied.LastIndexOf( ".cpp" );*/
}

#include <core/memory/AELinearAllocator.h>
/*
void MemoryTest()
{
	AEStackAllocator test(10000);

	AEMemoryManager ll;

	//AEFreeListAllocator freeList( 64, &test );
	AEFreeListAllocator freeList;
	ll.SetHeapAllocator( &freeList );

	AEBoundingBox *lpBB = new AEBoundingBox();

	lpBB->SetFromValues( 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f );

	AETString<char> *lpstr1 = new AETString<char>( "Gianluca Belardelli" );
	AETString<char> *lpstr2 = new AETString<char>( "Gianluca Belardelli e Daniela Mancini" );
	
	delete lpBB;
	delete lpstr1;

	AETString<char> str3( "Gianluca Belardelli e Daniela Mancini e Emma Cipollotta" );

	AEBoundingBox *lpBB1= new AEBoundingBox();
	lpBB1->SetFromValues( 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f );

	delete lpBB1;
}
*/
/*
void TestArray()
{
	AEStackAllocator test(10000);
	AEMemoryManager ll;
	ll.SetHeapAllocator( &test );

	//AETFixedSizeArray<int> intArray(8);
	AETArray<int> intArray;
	AETArray<float> floatArray;
	AETArray< AEBoundingBox > bbArray;
	AETArray< AEBoundingBox *> bblpArray;

	AEINT32 nCap = intArray.GetCapacity();
	AEINT32 nSize = intArray.GetSize();
	AEINT32 nCapFlags = intArray.GetCapacityAndFlags();

	//intArray[3] = 15;
	bbArray.PushBack( AEBoundingBox( 0.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f ) );
	AEBoundingBox bb = bbArray[0];

	intArray.PushBack( 10 );
	intArray.PushBack( 20 );
	intArray.PushBack( 30 );

	floatArray.PushBack( 15.5f );
	floatArray.PushBack( 25.5f );
	floatArray.PushBack( 35.5f );

	nCap = intArray.GetCapacity();
	nSize = intArray.GetSize();

	int val = intArray[0];
	val = intArray[1];
	val = intArray[2];

	float fval = floatArray[0];
	fval = floatArray[1];
	fval = floatArray[2];

	intArray.Clear();
	nCap = intArray.GetCapacity();
	nSize = intArray.GetSize();

}
*/
int sortIntAsc( const AEListNode<int> &lhs, const AEListNode<int> &rhs)
{
	if( lhs.m_tValue > rhs.m_tValue )
		return 1;
	else if( lhs.m_tValue < rhs.m_tValue )
		return -1;
	else return 0;
}

int sortIntDesc( const AEListNode<int> &lhs, const AEListNode<int> &rhs)
{
	if( lhs.m_tValue < rhs.m_tValue )
		return 1;
	else if( lhs.m_tValue > rhs.m_tValue )
		return -1;
	else return 0;
}
/*
void TestAETList()
{
	AEStackAllocator test(1024);
	AEFreeListAllocator flFreeList( 8 * 1024 );
	AEMemoryManager ll;
	ll.SetHeapAllocator( &flFreeList );

	AETList<int> intList;

	intList.RemoveAll();
	intList.AddElement( 30 );
	intList.AddElement( 20 );
	intList.AddElement( 10 );
	intList.AddElement( 10 );
	intList.AddElement( 11 );
	intList.AddElement( 15 );
	intList.AddElement( 12 );

	intList.Sort( sortIntDesc );

	int ref=0;
	AEListNode<int> *node = intList.GetFirst();

	while( node )
		node = intList.GetNext();

	int val = intList[1];
	val = intList[3];

	unsigned int i = intList.GetSize();
	bool bEmpty = intList.IsEmpty();

	bool bRes = intList.AddUniqueElement(10);
	bRes = intList.AddUniqueElement(11);

	i = intList.GetSize();

	bRes = intList.Remove( 21 );


	bRes = intList.Remove( 10 );
	//intList.Remove( intList.m_lpFront );
	i = intList.GetSize();
	
	//bRes = intList.RemoveFront( val );

	val = intList[1];

	AETList<AEVector4f> vcList;

	vcList.AddElement( AEVector4f( 10.0f, 10.0f, 10.0f, 0.0f ) );
	vcList.AddElement( AEVector4f( 20.0f, 20.0f, 20.0f, 0.0f ) );
	vcList.AddElement( AEVector4f( 30.0f, 30.0f, 30.0f, 0.0f ) );
	
	i = vcList.GetSize();
	bEmpty = vcList.IsEmpty();

	bRes = vcList.AddUniqueElement( AEVector4f( 10.0f, 10.0f, 10.0f, 0.0f ) );
	bRes = vcList.AddUniqueElement( AEVector4f( 11.0f, 10.0f, 10.0f, 0.0f ) );

	i = vcList.GetSize();

	typedef struct test
	{
		int val1;
		AEVector4f vec;
	}Test, *lpTest;

	AETList<Test *> testList;

	Test prova;
	prova.val1 = 10;
	prova.vec.Set(0.0,0.0,0.0, 0.0f);

	Test prova2;
	prova2.val1 = 10;
	prova2.vec.Set(0.0,0.0,0.0, 0.0f);

	Test prova3;
	prova3.val1 = 10;
	prova3.vec.Set(0.0,0.0,0.0, 0.0f);

	testList.AddElement( &prova );
	testList.AddElement( &prova2 );
	testList.AddUniqueElement( &prova3 );

	bRes = testList.Contains( &prova2 );
	testList.Remove( &prova2 );
	bRes = testList.Contains( &prova2 );
	testList.AddElement( &prova2 );
}
*/
#include <core\memory\AEMiniAllocator.h>


//AE_DECLARE_PLACEMENT_ALLOCATOR();
/*
void TestMiniAllocator()
{
	//

	AEMiniAllocator *lpTest;
	AEStackAllocator test(324);
	AEMemoryManager::GetInstance().SetHeapAllocator( &test );

	//lpTest = new AEMiniAllocator(44);

	lpTest = (AEMiniAllocator *)test.BlockAlloc( sizeof( AEMiniAllocator ) );
	//new ( lpTest ) AEMiniAllocator(25);

//	lpTest->Init( 256, &test );

	AEBoundingBox *array[1000];

	printf("sizeof comlex=%d\n", sizeof(AEBoundingBox) );
	int nCount=0;
	DWORD dwStart = timeGetTime();

	for (int i = 0;i  <  5000; i++) {
		for (int j = 0; j  <  1000; j++) {
			//array[j] = (AEBoundingBox *)lpTest->BlockAlloc( sizeof( AEBoundingBox ) );
			//new ( array[j] ) AEBoundingBox();
			array[j] = new AEBoundingBox();
			//array[j]->SetFromValues( 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 );
			//
		}
	}
}

void TestBoundingBox()
{
	AEBoundingBox bb = AEBoundingBox::CreateEmptyAABB();
	
	bb.SetFromCenterRadius( AEVector4f(4.0, 4.0, 4.0, 4.0), 23.0f );

	AEBOOL32 bRes = bb.IsValid();
	bRes = bb.IsEmpty();
	bb.GetCenter();
}


void* aligned_malloc(size_t size, size_t alignment) 
{
    const uintptr_t r = (uintptr_t)malloc(size + --alignment + sizeof(uintptr_t));
    uintptr_t t = r + sizeof(uintptr_t);
    uintptr_t o =(t + alignment) & ~(uintptr_t)alignment;
    if (!r) return NULL;
    ((uintptr_t*)o)[-1] = r;
    return (void*)o;
}
 
void aligned_free(void* p) {
    if (!p) return;
    free((void*)(((uintptr_t*)p)[-1]));
}
*/
#include <mmsystem.h>
/*
int memtest()
{
	//Obiettivo 100ms circa
	//AEFreeListAllocator test(2048);

	//AETString<char> testStr;

	//AEMemoryManager::GetInstance().SetHeapAllocator( &test );
	AEStackAllocator test(64);
	AEMemoryManager::GetInstance().SetHeapAllocator( &test );

//	AEBoundingBox *lpBox1 = (AEBoundingBox *)test.BlockAlloc( sizeof( AEBoundingBox ) );
//	lpBox1->SetFromValues( 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 );

	AEBoundingBox *array[1000];

	array[0] = new AEBoundingBox();
	array[1] = new AEBoundingBox();
	array[2] = new AEBoundingBox();

	delete array[2];
	delete array[1];
	delete array[0];
	delete array[1];

	*/
	/*
	printf("sizeof comlex=%d\n", sizeof(AEBoundingBox) );
	int nCount=0;
	DWORD dwStart = timeGetTime();

	for (int i = 0;i  <  5000; i++) {
		for (int j = 0; j  <  1000; j++) {
			//array[j] = (AEBoundingBox *)test.BlockAlloc( sizeof( AEBoundingBox ) );
			array[j] = new AEBoundingBox();
			//array[j]->SetFromValues( 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 );
			//nCount++;
		}
	
		//test.Clear();
		for (int j = 0; j  <  1000; j++) {
			delete array[j];
		}
	}

	printf("Alloc Time: %dms\n", timeGetTime()-dwStart);
	printf("nCount = %d\n", nCount );
	
	return 0;
  }  
  */
class testref : public AEReferencedObject
{
	int val;
public:
	testref() : val(0) {};

	int getVal() { return val; }
	void setVal(int nval) { val = nval; }
};

AERefNew<testref> testrefreturn(AESmartPtr<testref> ref)
{
	AESmartPtr<testref> ref1 = ref.GetPtr();
	ref1->setVal(15);

	AERefNew<testref> test = ref1.GetPtr();
	
	return test;
}
/*
void TestRefObjects()
{
	void *ptr = ::operator new(1000);

	AEStackAllocator test(32000);
	AEMemoryManager::GetInstance().SetHeapAllocator( &test );

	testref *lpref = new testref();
	lpref->setVal(5);

	int val = lpref->GetReferenceCount();
	val = lpref->GetAllocatedSize();

	
	AESmartPtr<testref> ref( new testref() );
	val = ref->getVal();
	val = ref->GetAllocatedSize();

	val=ref->GetReferenceCount();

	{
		AESmartPtr<testref> ref1 = ref;
		val = ref1->GetReferenceCount();
		val = ref->GetReferenceCount();
	}

	testref *lpPtr = ref;
	val=ref->GetReferenceCount();
	AERefNew<testref> test1 = testrefreturn( ref );

	ref=test1;

	val=ref->GetReferenceCount();
	AESmartPtr<testref> ref2 = ref;
	val=ref->GetReferenceCount();
	val=ref2->GetReferenceCount();

	delete ref;
	delete lpPtr;
	delete ref.GetPtr();
}
*/
DWORD WINAPI threadFn( void *lpParam )
{
	printf("Enter thread");
	Sleep( 10000 );
	printf("Exit thread");

	return 1;
}

void TestThreads()
{
	AEThread thread;


	thread.StartThread( (AEThread::AEStartFunction*)&threadFn, NULL, "Ciao" );
	printf("join thread\n");
	thread.JoinThread();
	printf("join thread end\n");
	//CloseHandle( m_lpThread );
}